home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / wwiv.arc / COMMON.PAS < prev    next >
Pascal/Delphi Source File  |  1986-04-07  |  31KB  |  1,198 lines

  1. CONST strlen=160;
  2.       comnum=1;
  3.       maxbaud=1200;
  4.       maxusers=500;
  5.       dsaves : Integer = 0;
  6.       buffer_Max    = 5120;
  7.       comptyp:array[1..8] of string[14]=('IBM','APPLE','TRS-80','Z-80 CP/M',
  8.                  'COMMODORE','ATARI','DUMB TERMINAL','OTHER');
  9.  
  10. TYPE str=string[strlen];
  11.      restrictions=(rlogon,rchat,rvalidate,rbackspace,ramsg,rpostan,
  12.                    rpost,remail,rvoting,rmsg);
  13.      acrq='@'..'G';
  14.      newtyp=(rp,lt,rm);
  15.      deflts=(spcsr,onekey,wordwrap,pause);
  16.      anontyp=(no,yes,forced,dearabby);
  17.      ansttype=(postn,emailn,pana,sanm,cosysop,lcosysop);
  18.      opts=(alert,smw,nomail);
  19.      pnr=record name:string[40]; number:string[14]; hs:byte; end;
  20.      slr=record
  21.            ttime:byte;
  22.            mallowed:integer;
  23.            emails,posts:byte;
  24.            anst:set of ansttype;
  25.          end;
  26.      messages=record
  27.                 ltr:char;
  28.                 number:integer;
  29.                 ext:byte;
  30.               end;
  31.      smalrec=record
  32.                name:string[25];
  33.                number:integer;
  34.              end;
  35.      userrec=record
  36.                name:string[25];
  37.                realname:string[14];
  38.                deleted:boolean;
  39.                pw:string[8];
  40.                ph:string[12];
  41.                waiting:byte;
  42.                laston:string[10];
  43.                loggedon:integer;
  44.                msgpost:integer;
  45.                emailsent:integer;
  46.                feedback:integer;
  47.                linelen:byte;
  48.                pagelen:byte;
  49.                defaults:set of deflts;
  50.                ontoday:byte;
  51.                illegal:byte;
  52.                cursor:string[10];
  53.                sl:byte;
  54.                ac:set of restrictions;
  55.                ar:set of acrq;
  56.                qscan:array[1..19] of messages;
  57.                qscn:array[1..19] of boolean;
  58.                macro:array[1..2] of string[79];
  59.                comptype:byte;
  60.                option:set of opts;
  61.                vote:array[1..9] of byte;
  62.                sbn:byte;
  63.                dsl:byte;
  64.                uploads,downloads:integer;
  65.                uk,dk:integer;
  66.              end;
  67.       boardrec=record
  68.                  name:string[25];
  69.                  filename:string[12];
  70.                  sl:byte;
  71.                  maxmsgs:byte;
  72.                  pw:string[10];
  73.                  anonymous:anontyp;
  74.                  ar:acrq;
  75.                  key:char;
  76.                end;
  77.       msgstat=(validated,unvalidated,deleted);
  78.       messagerec=record
  79.                    title:string[30];
  80.                    messagestat:msgstat;
  81.                    message:messages;
  82.                    owner:integer;
  83.                    date:integer;
  84.                    mage:byte;
  85.                  end;
  86.       systatrec=record
  87.                   boardpw:string[8];
  88.                   sysoppw:string[8];
  89.                   hmsg:messages;
  90.                   users:integer;
  91.                   lastdate:string[8];
  92.                   callernum:integer;
  93.                   activetoday:integer;
  94.                   callstoday:integer;
  95.                   msgposttoday:integer;
  96.                   emailtoday:integer;
  97.                   fbacktoday:integer;
  98.                   uptoday:integer;
  99.                   closedsystem:boolean;
  100.                 end;
  101.       blk=array[1..255] of byte;
  102.       mailrec=record
  103.                 title:string[30];
  104.                 from,destin:integer;
  105.                 msg:messages;
  106.                 date:integer;
  107.                 mage:byte;
  108.               end;
  109.       gft=record
  110.             num:integer;
  111.             title:string[40];
  112.             filen:string[12];
  113.           end;
  114.       charfil=text;
  115.       smr=record
  116.             msg:str;
  117.             destin:integer;
  118.           end;
  119.       vdatar=record
  120.                question:string[79];
  121.                numa:integer;
  122.                answ:array[0..9] of record
  123.                       ans:string[25];
  124.                       numres:integer;
  125.                     end;
  126.              end;
  127.       regs=record ax,bx,cx,dx,bp,si,di,ds,es,flags:integer; end;
  128.       ulrec=record
  129.               name:string[25];
  130.               filename:string[12];
  131.               password:string[10];
  132.               dsl:byte;
  133.               maxfiles:integer;
  134.             end;
  135.       ulfrec=record
  136.                filename:string[12];
  137.                description:string[60];
  138.                res:array[1..17] of byte;
  139.                ft:array[1..3] of byte;
  140.                blocks:integer;
  141.                owner:integer;
  142.                date:string[8];
  143.                daten:integer;
  144.              end;
  145.       strptr=^strrec;
  146.       strrec=record
  147.                i:str;
  148.                next,last:strptr;
  149.              end;
  150.  
  151. var sf:file of smalrec;
  152.     uf:file of userrec;
  153.     bf:file of boardrec;
  154.     mf:file of messagerec;
  155.     mailfile:file of mailrec;
  156.     sysopf:charfil;
  157.     slf:file of slr;
  158.     seclev:array[0..255] of slr;
  159.     systatf:file of systatrec;
  160.     systat:systatrec;
  161.     sr:smalrec;
  162.     thisline,chatr,buf,spd,irt,lastname,ll,cursor,i:str;
  163.     thisuser,user:userrec;
  164.     boards:array[1..19] of boardrec;
  165.     fw,extramsgs,mread,board,numboards,t,usernum:integer;
  166.     pap,lil,realsl,ftoday,ptoday,etoday:integer;
  167.     c,ID:char;
  168.     hungup,useron,next,chatcall,expert,doneday,echo,hangup,incom,outcom:boolean;
  169.     extratime,timeon:real;
  170.     macok,lan,enddayf,ch,quit:boolean;
  171.     buffer:Array[0..buffer_Max] of Char;
  172.     comport,base:Integer;
  173.     Async_Irq:Integer;
  174.     buffer_Head,buffer_tail,buffer_newtail:Integer;
  175.     smf:file of smr;
  176.     srl:array[0..maxusers] of smalrec;
  177.     vqu:array[1..9] of boolean;
  178.     ret:byte absolute cseg:$0080;
  179.     ldate:integer;
  180.     maxspd:integer;
  181.     cmd:char;
  182.     help:array[1..25000] of char;
  183.     helpi:array['0'..'^'] of integer;
  184.     helpl:char;
  185.     ihelp:boolean;
  186.     cf:text; cfo,okt:boolean;
  187.     elevel:byte;
  188.  
  189.  
  190. function freek:integer;
  191. var r:regs;
  192. begin
  193.   r.ax:=$3600;
  194.   r.dx:=0;
  195.   msdos(r);
  196.   freek:=trunc(1.0*r.bx*r.ax*r.cx/1024.0);
  197. end;
  198.  
  199. function cs:boolean;
  200. begin
  201.   cs:=cosysop in seclev[thisuser.sl].anst;
  202. end;
  203.  
  204. function so:boolean;
  205. begin
  206.   so:=thisuser.sl=255;
  207. end;
  208.  
  209. function lcs:boolean;
  210. begin
  211.   lcs:=cs or ((lcosysop in seclev[thisuser.sl].anst) and ((board=thisuser.sbn) or (thisuser.sbn=0)));
  212. end;
  213.  
  214. function commpressed : boolean;
  215. begin
  216.  commpressed := (buffer_tail<>buffer_head);
  217. end;
  218.  
  219. procedure dump;
  220. begin
  221.   inline($FA);
  222.   buffer_head:=0;
  223.   buffer_tail:=buffer_head;
  224.   inline($FB);
  225. end;
  226.  
  227. procedure async_isr;
  228. begin
  229.   inline($50/$53/$52/$1E/$FB/$2E/$FF/$36/dsaves/$1F/$8B/$16/base/
  230.          $EC/$8B/$1E/buffer_Head/$88/$87/buffer/$43/$81/$FB/buffer_Max/$7E/
  231.          $02/$33/$DB/$3B/$1E/buffer_Tail/$74/$04/$89/$1E/buffer_Head/$FA/
  232.          $B0/$20/$E6/$20/$1F/$5A/$5B/$58/$5C/$5D/$CF);
  233. end;
  234.  
  235. procedure remove_port;
  236. var
  237.   i,m:integer;
  238. begin
  239.   inline($FA);
  240.   i := port[$21];
  241.   m := 1 shl Async_Irq;
  242.   port[$21] := i or m;
  243.   port[2+base] := 0;
  244.   port[4+base] := 1;
  245.   inline($FB);
  246. end;
  247.  
  248. procedure term_ready(s:Boolean);
  249. var x:byte;
  250. begin
  251.   x := port[4+base] and $FE;
  252.   if s then x:=x+1;
  253.   port[4+base] := x;
  254. end;
  255.  
  256. procedure set_baud(r:integer);
  257. var rl:real; a:byte;
  258. begin
  259.   if (r>=300) and (r<=9600) then begin
  260.     rl:=115200.0/r;
  261.     r:=trunc(rl);
  262.     a:=port[3+base] or 128;
  263.     port[base+3]:=a;
  264.     port[base]:=lo(r);
  265.     port[1+base]:=hi(r);
  266.     port[3+base]:=a and 127;
  267.   end;
  268. end;
  269.  
  270.  
  271. procedure iport;
  272. var
  273.    i,m:Integer;
  274.    regs:record ax,bx,cx,dx,bp,si,di,ds,es,flags:integer; end;
  275. begin
  276.   dsaves:= DSeg;
  277.   If ComPort = 2 Then begin
  278.     base := $2f8;
  279.     Async_Irq  := 3;
  280.   end else begin
  281.     base := $3f8;
  282.     Async_Irq  := 4;
  283.   end;
  284.   If (Port[2+base] and $00F8) <> 0 Then
  285.     begin writeln('Illegal com port number'); halt; end
  286.   else begin
  287.     buffer_Head:=0; buffer_Tail:=0; port[base+3]:=$03;
  288.     with regs do begin
  289.       ax:=$2500+((async_irq+8) and $00ff); ds:=cseg;
  290.       dx:=ofs(async_isr); msdos(regs);
  291.     end;
  292.     inline($FA);
  293.     i:=port[5+base];
  294.     i:=port[base];
  295.     i:=port[$21];
  296.     m:=(1 shl Async_Irq) xor $00FF;
  297.     port[$21] := i and m;
  298.     port[1+base] := $01;
  299.     i := port[4+base];
  300.     port[4+base] := i or $08;
  301.     term_ready(true);
  302.     inline($FB);
  303.   end;
  304. end;
  305.  
  306. function cinkey:char;
  307. var t:char;
  308. begin
  309.   if buffer_Head = buffer_Tail Then
  310.     t:=#0
  311.   else begin
  312.     inline($FA);
  313.     t:=buffer[buffer_Tail];
  314.     buffer_Tail:=(buffer_Tail+1) mod (buffer_max+1);
  315.     inline($FB);
  316.   end;
  317.   cinkey:=chr(ord(t) and 127);
  318. end;
  319.  
  320. function cinkey1:char;
  321. var t:char;
  322. begin
  323.   if buffer_Head = buffer_Tail Then
  324.     t:=#0
  325.   else begin
  326.     inline($FA);
  327.     t:=buffer[buffer_Tail];
  328.     buffer_Tail:=(buffer_Tail+1) mod (buffer_max+1);
  329.     inline($FB);
  330.   end;
  331.   cinkey1:=t;
  332. end;
  333.  
  334. procedure o1(c:char);
  335. begin
  336.   while (port[base+5] and 32)=0 do;
  337.   port[base]:=ord(c);
  338. end;
  339.  
  340. procedure o(c:char);
  341. begin
  342.   if outcom and (c<>#1) then o1(c);
  343. end;
  344.  
  345. FUNCTION TIMER: REAL;
  346.  
  347. VAR REG: RECORD
  348.            AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: INTEGER;
  349.          END;
  350.     H,M,S,T: REAL;
  351.  
  352. BEGIN
  353.   REG.AX := 44 * 256;
  354.   MsDos(REG);
  355.   H      := (REG.CX DIV 256);
  356.   M      := (REG.CX MOD 256);
  357.   S      := (REG.DX DIV 256);
  358.   T      := (REG.DX MOD 256);
  359.   TIMER  := H*3600 + M*60 + S + T/100;
  360. END;
  361.  
  362. function sysop1:boolean;
  363. begin
  364.   if (mem[0:1047] and 16)=0 then sysop1:=false else sysop1:=true;
  365. end;
  366.  
  367. function sysop:boolean;
  368. begin
  369.   sysop:=sysop1;
  370.   if rchat in thisuser.ac then sysop:=false;
  371. end;
  372.  
  373. procedure bs;
  374. var x,y:integer;
  375. begin
  376.   x:=wherex; y:=wherey; if x>1 then x:=x-1 else
  377.     if y>1 then begin x:=80; y:=y-1; end;
  378.   gotoxy(x,y);
  379. end;
  380.  
  381. procedure backs;
  382. begin
  383.   o(chr(8)); bs; write(' '); o(' '); o(chr(8)); bs;
  384. end;
  385.  
  386. procedure sl1(i:str);
  387. begin
  388.   if (realsl<>255) or incom then begin
  389.     assign(sysopf,'gfiles\sysop.log'); {$I-} append(sysopf);{$I+}
  390.     if ioresult<>0 then
  391.       rewrite(sysopf);
  392.     writeln(sysopf,i);
  393.     close(sysopf);
  394.   end;
  395. end;
  396.  
  397. procedure sysoplog(i:str);
  398. begin
  399.   sl1('   '+i);
  400. end;
  401.  
  402. function tch(i:str):str;
  403. begin
  404.   if length(i)>2 then i:=copy(i,length(i)-1,2) else
  405.     if length(i)=1 then i:='0'+i;
  406.   tch:=i;
  407. end;
  408.  
  409. FUNCTION TIME:STR;
  410. VAR REG: RECORD
  411.            AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: INTEGER;
  412.          END;
  413.     H,M,S:string[4];
  414. BEGIN
  415.   reg.ax:=$2c00; intr($21,reg);
  416.   str(reg.cx shr 8,h); str(reg.cx mod 256,m); str(reg.dx shr 8,s);
  417.   time:=tch(h)+':'+tch(m)+':'+tch(s);
  418. END;
  419.  
  420. FUNCTION DATE:STR;
  421. VAR REG: RECORD
  422.            AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: INTEGER;
  423.          END;
  424.     M,D,Y:STRing[4];
  425. BEGIN
  426.   reg.ax:=$2a00; msdos(reg); str(reg.cx,y); str(reg.dx mod 256,d);
  427.   str(reg.dx shr 8,m);
  428.   date:=tch(m)+'/'+tch(d)+'/'+tch(y);
  429. END;
  430.  
  431. FUNCTION value(I:str):INTEGER;
  432. VAR N,N1:INTEGER;
  433. BEGIN
  434.   VAL(I,N,N1);
  435.   IF N1<>0 THEN BEGIN
  436.     I:=COPY(I,1,N1-1);
  437.     VAL(I,N,N1)
  438.   END;
  439.   VaLue:=N;
  440.   if i='' then value:=0;
  441. END;
  442.  
  443.  
  444. function cstr(i:integer):str;
  445. var c:str;
  446. begin
  447.   str(i,c); cstr:=c;
  448. end;
  449.  
  450. function nam:str;
  451. var s:str; i:integer; tf:boolean;
  452. begin
  453.   s:=thisuser.name;
  454.   tf:=true;
  455.   for i:=1 to length(s) do
  456.     if s[i]<'A' then
  457.       tf:=true
  458.     else begin
  459.       if (s[i]<='Z') and not tf then
  460.         s[i]:=chr(ord(s[i])+32);
  461.       tf:=false;
  462.     end;
  463.   nam:=s+' #'+cstr(usernum);
  464. end;
  465.  
  466.  
  467. function leapyear(yr:integer):boolean;
  468. begin
  469.   leapyear:=(yr mod 4=0) and ((yr mod 100<>0) or (yr mod 400=0));
  470. end;
  471.  
  472. function days(mo,yr:integer):integer;
  473. var d:integer;
  474. begin
  475.   d:=value(copy('312831303130313130313031',1+(mo-1)*2,2));
  476.   if (mo=2) and leapyear(yr) then d:=d+1;
  477.   days:=d;
  478. end;
  479.  
  480. function daycount(mo,yr:integer):integer;
  481. var m,t:integer;
  482. begin
  483.   t:=0;
  484.   for m:=1 to (mo-1) do t:=t+days(m,yr);
  485.   daycount:=t;
  486. end;
  487.  
  488. function daynum(dt:str):integer;
  489. var d,m,y,t,c:integer;
  490. begin
  491.   t:=0;
  492.   m:=value(copy(dt,1,2));
  493.   d:=value(copy(dt,4,2));
  494.   y:=value(copy(dt,7,2))+1900;
  495.   for c:=1985 to y-1 do
  496.     if leapyear(c) then t:=t+366 else t:=t+365;
  497.   t:=t+daycount(m,y)+(d-1);
  498.   daynum:=t;
  499.   if y<1985 then daynum:=0;
  500. end;
  501.  
  502. function dat:str;
  503. var ap,x,y:str; i:integer;
  504. begin
  505.   case daynum(date) mod 7 of
  506.     0:x:='Tue';
  507.     1:x:='Wed';
  508.     2:x:='Thu';
  509.     3:x:='Fri';
  510.     4:x:='Sat';
  511.     5:x:='Sun';
  512.     6:x:='Mon';
  513.   end;
  514.   case value(copy(date,1,2)) of
  515.     1:y:='Jan';
  516.     2:y:='Feb';
  517.     3:y:='Mar';
  518.     4:y:='Apr';
  519.     5:y:='May';
  520.     6:y:='Jun';
  521.     7:y:='Jul';
  522.     8:y:='Aug';
  523.     9:y:='Sep';
  524.     10:y:='Oct';
  525.     11:y:='Nov';
  526.     12:y:='Dec';
  527.   end;
  528.   x:=x+' '+y+' '+copy(date,4,2)+', '+cstr(1900+value(copy(date,7,2)));
  529.   y:=time; i:=value(copy(y,1,2));
  530.   if i>11 then ap:='pm' else ap:='am';
  531.   if i>12 then i:=i-12;
  532.   if i=0 then i:=12;
  533.   dat:=cstr(i)+copy(y,3,3)+' '+ap+'  '+x;
  534. end;
  535.  
  536. function cdet:boolean;
  537. begin
  538.   cdet:=(port[base+6] and 128)<>0;
  539. end;
  540.  
  541. procedure checkhangup;
  542. begin
  543.   if incom and not cdet and (not hangup) then begin
  544.     hangup:=true; hungup:=true;
  545.   end;
  546. end;
  547.  
  548. procedure topscr; forward;
  549. procedure skey(c:char); forward;
  550. procedure getkey(var c:char); forward;
  551.  
  552. procedure pr1(i:str);
  553. var c:integer;
  554. begin
  555.   for c:=1 to length(i) do o1(i[c]);
  556. end;
  557.  
  558. procedure pr(i:str);
  559. begin
  560.   pr1(i+#13);
  561. end;
  562.  
  563. procedure prompt(i:str);
  564. var c:integer; cc:char;
  565. begin
  566.  checkhangup;
  567.  if not hangup then begin
  568.   for c:=1 to length(i) do begin
  569.     if (not ((i[c]=chr(7)) and (incom))) and (i[c]<>chr(12)) and (i<>#1) then write(i[c]);
  570.     if chatcall then sound(1000);
  571.     o(i[c]);
  572.     if i[c]>#31 then thisline:=thisline+i[c];
  573.     if i[c]=#8 then if length(thisline)>0 then thisline:=copy(thisline,1,length(thisline)-1);
  574.     if i[c]=chr(12) then begin lil:=0; clrscr; topscr; end;
  575.     if i[c]=chr(13) then begin pap:=0; thisline:=''; end;
  576.     nosound;
  577.     if i[c]=chr(10) then begin
  578.       lil:=lil+1;
  579.       if (lil>=thisuser.pagelen-1) then begin
  580.         lil:=0;
  581.         if pause in thisuser.defaults then begin
  582.           prompt('(-*-)');
  583.           getkey(cc); skey(cc); prompt(' '+chr(8));
  584.           for cc:='A' to 'E' do
  585.             prompt(chr(8)+' '+chr(8));
  586.         end;
  587.       end;
  588.     end;
  589.   end;
  590.  end;
  591. end;
  592.  
  593. procedure print(i:str);
  594. begin
  595.   prompt(i+chr(13)+chr(10))
  596. end;
  597.  
  598.  
  599. procedure nl;
  600. begin
  601.   prompt(chr(13)+chr(10))
  602. end;
  603.  
  604. procedure tleft;
  605. var x,y:integer;
  606. begin
  607.  if okt then begin
  608.   x:=wherex; y:=wherey; window(1,1,80,4);
  609.   gotoxy(72,3);if chatcall then begin
  610.     write('CHAT ON');
  611.     if alert in thisuser.option then begin
  612.       gotoxy(72,3);
  613.       write('ALERT  ');
  614.     end;
  615.   end else write('       ');
  616.   gotoxy(56,3); if sysop1 then write('Sysop Available') else
  617.     write('----- ---------');
  618.   if useron then begin
  619.     gotoxy(35,3); if thisuser.ontoday<>1 then write('ML=',extramsgs+seclev[thisuser.sl].mallowed-mread,'   ');
  620.     gotoxy(45,3); write('TL=',((seclev[thisuser.sl].ttime*60+extratime+timeon-timer)/60):6:2,'  ');
  621.   end;
  622.   if hangup then begin
  623.     gotoxy(72,3);
  624.     write('HANG UP');
  625.   end;
  626.   window(1,5,80,25);gotoxy(x,y);
  627.   if timer<timeon then timeon:=timeon-24.0*60*60;
  628.   if not ch and ((seclev[thisuser.sl].ttime*60+extratime+timeon-timer)<0) and useron then
  629.   begin nl; print('Time expired.'); hangup:=true; end;
  630.   checkhangup;
  631.  end;
  632. end;
  633.  
  634.  
  635. procedure prestrict(u:userrec);
  636. var r:restrictions;
  637. begin
  638.   for r:=rlogon to rmsg do
  639.     if r in u.ac then write(copy('LCVBA*PEKM',ORD(R)+1,1)) else write(' ');
  640.   writeln;
  641. end;
  642.  
  643. procedure ff(i:integer);
  644. begin
  645.   while wherex<i do write(' ');
  646. end;
  647.  
  648. procedure topscr;
  649. var c:char; x,y,i:integer;
  650. begin
  651.  if (usernum<>0) and okt then begin
  652.   x:=wherex; y:=wherey;
  653.   window(1,1,80,5);
  654.   gotoxy(1,1); write(chr(186),' ',nam); ff(35);
  655.   with thisuser do begin
  656.     write(realname);ff(50);write(ph);ff(65);
  657.     if laston<>date then write(laston);
  658.     ff(76); if date=laston then write(ontoday); ff(79);
  659.     write(' ',chr(186));gotoxy(1,2);
  660.     write(chr(186),' SL=',sl);ff(10);write('AR=');
  661.     for c:='A' to 'G' do if c in ar then write(c) else write(' ');
  662.     write(' LO=',loggedon);
  663.     ff(28);write('P=',msgpost);ff(35);write('E=',emailsent);
  664.     ff(42);write('F=',feedback);ff(48);
  665.     write('W=',waiting);ff(54);
  666.     if not useron then write('"',pw,'"') else write('SC=',thisuser.linelen,'X',
  667.       thisuser.pagelen,'   ');
  668.     ff(68);write('FW=',fw); ff(74); write('D=',thisuser.dsl);
  669.     gotoxy(80,2);write(#186);
  670.     gotoxy(1,3);write(#186,' AC='); prestrict(thisuser);
  671.     gotoxy(17,3);write('C=',comptyp[thisuser.comptype]);
  672.     gotoxy(80,3);write(chr(186));
  673.     gotoxy(1,4);write(chr(200));
  674.     for i:=2 to 79 do
  675.       write(chr(205));
  676.     write(chr(188));
  677.   end;
  678.   window(1,5,80,25);gotoxy(x,y);
  679.   tleft;
  680.  end;
  681. end;
  682.  
  683. function empty:boolean;
  684. begin
  685.   if incom then empty:=not commpressed else empty:=true;
  686.   if keypressed then empty:=false;
  687.   if hangup then begin dump; empty:=true; end;
  688. end;
  689.  
  690. function inkey:char;
  691. var c:char;
  692. begin
  693.   c:=chr(0); inkey:=chr(0);
  694.   if keypressed then begin
  695.     read(kbd,c); if c=chr(27) then
  696.       if keypressed then begin
  697.         read(kbd,c);
  698.         c:=chr(ord(c) or 128);
  699.       end;
  700.     inkey:=c;
  701.   end else begin
  702.     if commpressed and incom then begin
  703.       inkey:=cinkey;
  704.     end;
  705.   end;
  706. end;
  707.  
  708. procedure oc(c:char);
  709. begin
  710.   if c=chr(8) then bs else if c<>chr(0) then write(C);
  711.   o(c);
  712. end;
  713.  
  714. procedure outkey(c:char);
  715. begin
  716.   if (c<>chr(12)) and (not ((c=chr(7)) and (incom))) then if c=chr(8) then bs else if c<>#0 then write(c);
  717.   if (not echo) and (c>=' ') then c:='X';
  718.   o(c);
  719.   if c=chr(12) then begin clrscr; topscr; end;
  720.   if c=#7 then begin o(#0); o(#0); o(#0); o(#0); end;
  721. end;
  722.  
  723. procedure phelp; forward;
  724. procedure ptime; forward;
  725.  
  726.  
  727. procedure getkey;
  728. var p:integer; t:real; tf,t1:boolean;
  729. begin
  730.  if buf<>'' then begin
  731.    c:=buf[1]; buf:=copy(buf,2,length(buf)-1);
  732.  end else if not empty then c:=inkey else begin
  733.  p:=1; t:=timer; t1:=false; tf:=false; lil:=0;
  734.  c:=chr(0);
  735.   while (c=chr(0)) and not hangup do begin
  736.     c:=inkey;
  737.     if empty and (c=chr(0)) then begin
  738.       if (spcsr in thisuser.defaults) then begin
  739.         oc(cursor[p]); t1:=true;
  740.         p:=p+1; if p>length(cursor) then p:=1;
  741.       end;
  742.     end;
  743.     if (timer-t)>180 then begin nl;
  744.       print('Call back later when you are there.');hangup:=true;
  745.       sysoplog('!-!-! TIMEOUT !-!-!');
  746.     end;
  747.     if ((timer-t)>90) and (not tf) then begin tf:=true; outkey(chr(7)); end;
  748.     checkhangup;
  749.   end;
  750. if (spcsr in thisuser.defaults) and t1 then begin
  751.  if (p mod 2)=0 then
  752.    oc(chr(8));
  753.  if (c<' ') or (c>=chr(127)) then begin oc(' '); oc(chr(8)); end;
  754. end;
  755. end;
  756. if c=chr(127) then c:=chr(8);
  757. if ((c=#6) or (c=#4)) and macok then begin
  758.   if c=#4 then
  759.     buf:=thisuser.macro[1]
  760.   else
  761.     buf:=thisuser.macro[2];
  762.   if buf<>'' then begin c:=buf[1]; buf:=copy(buf,2,length(buf)-1); end;
  763. end;
  764. end;
  765.  
  766. procedure cls;
  767. begin
  768.   outkey(chr(12));
  769. end;
  770.  
  771.  
  772. procedure chsl;
  773. var ij,i:str; c:integer;
  774. begin
  775.  ij:=thisline;
  776.  prompt('[WAIT]');
  777.  writeln;writeln;write('Enter new SL: ');
  778.  readln(i); if i<>'' then thisuser.sl:=value(i); writeln;
  779.  if thisuser.sl=99 then begin
  780.    write('Board #? '); thisuser.sbn:=0;
  781.    readln(i); thisuser.sbn:=value(i);
  782.    writeln;
  783.  end;
  784.  topscr; realsl:=thisuser.sl;
  785.  i:=''; for c:=1 to 6 do i:=i+chr(8)+' '+chr(8);
  786.  prompt(i);
  787.  writeln; thisline:=ij; write(ij);
  788. end;
  789.  
  790. procedure swac(var u:userrec;r:restrictions);
  791. begin
  792.   if r in u.ac then u.ac:=u.ac-[r] else u.ac:=u.ac+[r];
  793. end;
  794.  
  795. procedure acch(c:char; var u:userrec);
  796. begin
  797.   case c of
  798.     'L':swac(u,rlogon);
  799.     'C':SWAC(u,RCHAT);
  800.     'V':SWAC(u,RVALIDATE);
  801.     'B':SWAC(u,RBACKSPACE);
  802.     'A':SWAC(u,RAMSG);
  803.     '*':SWAC(u,RPOSTAN);
  804.     'P':SWAC(u,RPOST);
  805.     'E':SWAC(u,REMAIL);
  806.     'K':SWAC(u,RVOTING);
  807.     'M':swac(u,rmsg);
  808.   END;
  809. end;
  810.  
  811. procedure chac(var thisuser:userrec);
  812. var c:char; ij,i:str; cc:integer;
  813. begin
  814.   ij:=thisline;
  815.   prompt('[WAIT]');
  816.   writeln;writeln('LCVBA*PEKM');writeln;write('Which? '); read(kbd,c); c:=upcase(c); writeln(c); writeln;
  817.   acch(c,thisuser);
  818.   topscr;
  819.   i:=''; for cc:=1 to 6 do i:=i+chr(8)+' '+chr(8);
  820.   prompt(i);
  821.   writeln;
  822.   thisline:=ij; write(ij);
  823. END;
  824.  
  825. procedure chat; forward;
  826.  
  827. procedure chdsl;
  828. var ij,i:str; c:integer;
  829. begin
  830.  ij:=thisline;
  831.  prompt('[WAIT]');
  832.  writeln;writeln;
  833.  writeln('UL=',thisuser.uploads,'-',thisuser.uk,'K   DL=',thisuser.downloads,'-',thisuser.dk,'K');
  834.  write('Enter new DSL: ');
  835.  readln(i); if i<>'' then thisuser.dsl:=value(i); writeln;
  836.  i:=''; for c:=1 to 6 do i:=i+chr(8)+' '+chr(8);
  837.  topscr;
  838.  prompt(i);
  839.  writeln; thisline:=ij; write(ij);
  840. end;
  841.  
  842. procedure tfile;
  843. var i:str; ii:integer;
  844. bf:file of byte; cr:boolean;
  845. begin
  846.   if cfo then begin
  847.     cfo:=false;
  848.     close(cf);
  849.     write('<CLOSED>');
  850.   end else begin
  851.     assign(cf,'gfiles\chat.msg');
  852.     assign(bf,'gfiles\chat.msg'); cr:=false;
  853.     {$I-} reset(bf); {$I+}
  854.     if ioresult<>0 then cr:=true
  855.     else begin
  856.       if filesize(bf)=0 then cr:=true;
  857.       close(bf);
  858.     end;
  859.     if cr then rewrite(cf) else append(cf);
  860.     cfo:=true;
  861.     i:=#13+#10+#13+#10+dat+#13+#10+'==============='+#13+#10;
  862.     writeln(cf,i);
  863.     write('<OPEN>');
  864.   end;
  865. end;
  866.  
  867. procedure skey;
  868. var b:boolean;
  869. begin
  870.   case ord(c) of
  871.       3:if spcsr in thisuser.defaults then
  872.           thisuser.defaults:=thisuser.defaults-[spcsr] else
  873.           thisuser.defaults:=thisuser.defaults+[spcsr];
  874.      26:phelp;
  875.      20:ptime;
  876.     187:chsl;
  877.     212:chdsl;
  878.     188:chac(thisuser);
  879.     189:begin
  880.          if outcom then incom:=not incom;
  881.          writeln; if incom then writeln('<INPUT ENABLED>')
  882.            else writeln('<COM DISABLED>');
  883.          writeln;dump;
  884.          write(thisline);
  885.        end;
  886.     190:chatcall:=false;
  887.     195:begin
  888.           if thisuser.sl=255 then if realsl<>255 then begin
  889.             thisuser.sl:=realsl; writeln;writeln;writeln('<SECLEV RESTORED>');
  890.             writeln; write(thisline); end
  891.           else else begin
  892.             thisuser.sl:=255; writeln;writeln;writeln('<TEMP SYSOP GRANTED>');
  893.             writeln; write(thisline);
  894.           end; topscr;
  895.         end;
  896.     196:if not ch then chat;
  897.     199:if ch then tfile;
  898.     191:hangup:=true;
  899.     192:tleft;
  900.     193:begin b:=ch; ch:=true; extratime:=extratime-5*60; tleft; ch:=b;end;
  901.     194:begin b:=ch; ch:=true; extratime:=extratime+5*60; tleft; ch:=b;end;
  902.     218:begin b:=ch; ch:=true; extramsgs:=extramsgs-10; tleft; ch:=b;  end;
  903.     219:begin b:=ch; ch:=true; extramsgs:=extramsgs+10; tleft; ch:=b;  end;
  904.   end;
  905.   if (c>chr(127)) and (c<>chr(196)) then c:=chr(0);
  906. end;
  907.  
  908. procedure inli1(var i:str);
  909. var cp:integer; c:char; cv,cc:integer;
  910. begin
  911.   cp:=1;
  912.   i:='';
  913.   if ll<>'' then begin prompt(ll); i:=ll; ll:=''; cp:=length(i)+1;end;
  914.   repeat
  915.     getkey(c); skey(c); checkhangup;
  916.     case ord(c) of
  917.       32..126:if (cp<79) then begin
  918.                 i[cp]:=c; cp:=cp+1; outkey(c);
  919.               end;
  920.       127,8:if cp>1 then begin c:=chr(8);
  921.                prompt(c+' '+c); cp:=cp-1;
  922.             end;
  923.       24:begin
  924.            for cv:=1 to cp-1 do prompt(chr(8)+' '+chr(8)); cp:=1;
  925.          end;
  926.        7:o(#7);
  927.       23:if cp>1 then repeat
  928.            prompt(chr(8)+' '+chr(8)); cp:=cp-1;
  929.          until (cp=1) or (i[cp]=' ');
  930.        9:begin
  931.            cv:=5-(cp mod 5); if (cp+cv<79)  then
  932.              for cc:=1 to cv do begin
  933.                prompt(' ');
  934.                i[cp]:=' '; cp:=cp+1;
  935.              end;
  936.          end;
  937.   end;
  938.   until (c=#13) or (cp=79) or hangup or (c=#196);
  939.   if c=#196 then begin c:=#13; ch:=false; end;
  940.   i[0]:=chr(cp-1);
  941.   if c<>chr(13) then begin
  942.     cv:=cp-1;
  943.     while (cv>0) and (i[cv]<>' ') and (i[cv]<>chr(8))do cv:=cv-1;
  944.     if (cv>(cp div 2)) and (cv<>cp-1) then begin
  945.       ll:=copy(i,cv+1,cp-cv); for cc:=cp-2 downto cv do prompt(chr(8));
  946.       for cc:=cp-2 downto cv do prompt(' ');
  947.       i[0]:=chr(cv-1);
  948.     end;
  949.   end;
  950.   nl;
  951. end;
  952.  
  953. procedure chat;
  954. var c,ohl:char; tf:boolean; sp,xx:str; x:integer; t,t1:real;
  955. begin
  956.   sp:=thisline; ch:=true; chatcall:=false; tf:=echo; echo:=true;nl;nl; t:=timer;
  957.   thisuser.option:=thisuser.option-[alert]; ohl:=helpl; helpl:=#0;
  958.   print('Sysop''s here...'); nl;
  959.   if chatr<>'' then begin
  960.     writeln; writeln; writeln('Reason: ',chatr); writeln; writeln; chatr:='';
  961.   end;
  962.   repeat
  963.     inli1(xx);
  964.     if (xx='/quitchat') or (xx='/QUITCHAT') then begin
  965.       t1:=timer; while (abs(t1-timer)<4.0) and (not keypressed) do;
  966.       if not keypressed then ch:=false;
  967.     end else if cfo then writeln(cf,xx);
  968.   until (not ch) or hangup;
  969.   nl;print('Chat mode over...'); nl;
  970.   extratime:=extratime+timer-t; ch:=false; echo:=tf;
  971.   if hangup and cfo then begin
  972.     writeln(cf); writeln(cf,'<HANGUP>');
  973.   end;
  974.   prompt(sp); thisline:=sp;
  975.   if cfo then begin cfo:=false; close(cf); end;
  976.   helpl:=ohl;
  977. end;
  978.  
  979. function yn:boolean;
  980. var c:char;
  981. begin
  982.   if not hangup then begin
  983.     repeat
  984.       getkey(c);
  985.       skey(c);
  986.       c:=upcase(c);
  987.     until (c='Y') or (c='N') or (c=chr(13)) or hangup;
  988.     if c='Y' then begin print('Yes'); yn:=true; end else begin print('No'); yn:=false; end;
  989.     if hangup then yn:=false;
  990.   end;
  991. end;
  992.  
  993. procedure input1(var i:str; ml:integer; tf:boolean);
  994. var cp:integer;
  995.     c:char;
  996.     r:real;
  997. begin
  998.  checkhangup;
  999.  if not hangup then begin
  1000.   r:=timer;
  1001.   cp:=1;
  1002.   repeat
  1003.     getkey(c);
  1004.     skey(c);
  1005.     if c=#196 then r:=timer;
  1006.     if not tf then c:=upcase(c);
  1007.     if (c>=' ') and (c<chr(127)) then
  1008.       if cp<=ml then begin
  1009.       i[cp]:=c;
  1010.       cp:=cp+1;
  1011.       outkey(c);
  1012.       thisline:=thisline+c;
  1013.     end else else case ord(c) of
  1014.       127,8:if cp>1 then begin
  1015.                c:=chr(8);
  1016.                outkey(c);outkey(' '); outkey(c);
  1017.                cp:=cp-1;
  1018.                if length(thisline)>0 then thisline:=copy(thisline,1,length(thisline)-1);
  1019.              end;
  1020.       21,24:while cp<>1 do begin
  1021.                cp:=cp-1;
  1022.                outkey(#8);outkey(' '); outkey(#8);
  1023.                if length(thisline)>0 then thisline:=copy(thisline,1,length(thisline)-1);
  1024.              end;
  1025.     end;
  1026.     if (timer-r)>300.0 then hangup:=true;
  1027.   until (c=#13) or (c=#14) or hangup;
  1028.   i[0]:=chr(cp-1);
  1029.   nl;
  1030.  end;
  1031. end;
  1032.  
  1033. procedure input(var i:str; ml:integer);
  1034. begin
  1035.   input1(i,ml,false);
  1036. end;
  1037.  
  1038.  
  1039. procedure inputl(var i:str; ml:integer);
  1040. begin
  1041.   input1(i,ml,true);
  1042. end;
  1043.  
  1044. function find(c:char; s:str):boolean;
  1045. var i:integer; tf:boolean;
  1046. begin
  1047.   c:=upcase(c);
  1048.   tf:=false;
  1049.   for i:=1 to length(s) do
  1050.     if c=upcase(s[i]) then tf:=true;
  1051.   find:=tf;
  1052. end;
  1053.  
  1054. procedure onek(var c:char; ch:str);
  1055.  var i1,i:str; tf:boolean;
  1056. begin
  1057.   i1:=thisline; tf:=false;
  1058.   repeat
  1059.     if not(onekey in thisuser.defaults) then begin
  1060.       if tf then prompt(i1);
  1061.       input(i,3);
  1062.       if length(i)=1 then c:=i[1] else c:=' ';
  1063.     end else begin
  1064.       getkey(c);
  1065.       skey(c);
  1066.       c:=upcase(c);
  1067.     end;
  1068.     tf:=true;
  1069.   until find(c,ch) or hangup;
  1070.   if not find(c,ch) then c:=ch[1];
  1071.   if onekey in thisuser.defaults then print(''+c);
  1072. end;
  1073.  
  1074. procedure centre(var i:str);
  1075. begin
  1076.   if pap<>0 then nl;
  1077.   if i[1]=#2 then i:=copy(i,2,length(i)-1);
  1078.   if length(i)<thisuser.linelen then
  1079.     i:=copy('                                               ',1,
  1080.       (thisuser.linelen-length(i)) div 2)+i;
  1081. end;
  1082.  
  1083. procedure printa1(i:str; var abort,next:boolean);
  1084. var c:integer; cc:char;
  1085.  procedure wkey;
  1086.  begin
  1087.     while (not empty) and (not hangup) do begin
  1088.       cc:=inkey; skey(cc);
  1089.       if (cc=' ') or (cc=chr(3)) or (cc=chr(24)) or (cc=chr(11)) then
  1090.         abort:=true;
  1091.       if (cc=chr(14)) then begin abort:=true; next:=true; end;
  1092.       if (cc=chr(19)) or (cc='P') or (cc='p') then begin
  1093.         getkey(cc); skey(cc);
  1094.       end;
  1095.     end;
  1096.  end;
  1097.  
  1098. begin
  1099.  checkhangup;
  1100.  if not hangup then begin
  1101.   abort:=false; next:=false; c:=1;
  1102.   wkey;
  1103.   while (not abort) and (c-1<>length(i)) and (not hangup) do begin
  1104.     checkhangup;
  1105.     if i[c]=chr(8) then pap:=pap-1 else if i[c]<>chr(10) then pap:=pap+1;
  1106.     wkey;
  1107.     outkey(i[c]);
  1108.     c:=c+1;
  1109.   end;
  1110.  end else abort:=true;
  1111. end;
  1112.  
  1113. procedure printa(i:str; var abort,next:boolean);
  1114. var s:str; p,lp,rp:integer;
  1115. begin
  1116.   abort:=false;
  1117.   p:=1; rp:=0; lp:=1;
  1118.   if i[1]=#2 then begin
  1119.     if i[length(i)]=#1 then i:=copy(i,1,length(i)-1);
  1120.     centre(i);
  1121.     printa1(i,abort,next);
  1122.     nl;
  1123.   end else begin
  1124.     while (p<=length(i)) and (not abort) and (not hangup) do begin
  1125.       rp:=0;
  1126.       while (i[p]<>' ') and (p<=length(i)) and (not hangup) do begin
  1127.         if i[p]=chr(8) then rp:=rp-1 else
  1128.           if (i[p]<>#10) and (i[p]<>#1) then rp:=rp+1;
  1129.         p:=p+1;
  1130.       end;
  1131.       if i[p]=' ' then rp:=rp+1;
  1132.       s:=copy(i,lp,(p-lp+1)); p:=p+1; lp:=p;
  1133.       if s[length(s)]=#1 then s:=copy(s,1,length(s)-1);
  1134.       if s<>'' then if (copy(s,length(s),1)<>' ') and (i[length(i)]<>#1) then s:=s+' ';
  1135.       if (pap+rp>=thisuser.linelen) then nl;
  1136.       printa1(s,abort,next);
  1137.     end;
  1138.     if not abort then printa1('',abort,next);
  1139.     if abort or (i[length(i)]=#1) or (length(i)=0) then nl;
  1140.   end;
  1141. end;
  1142.  
  1143. procedure printacr(i:str; var abort,next:boolean);
  1144. begin
  1145.  if not abort then
  1146.   if i[length(i)]=#1 then
  1147.     printa(i,abort,next)
  1148.   else
  1149.     printa(i+#1,abort,next);
  1150. end;
  1151.  
  1152. function tlef:str;
  1153. var rl:real; inte:integer; i,ii:str;
  1154. begin
  1155.   rl:=(seclev[thisuser.sl].ttime*60.0+extratime+timeon-timer);
  1156.   if rl>32767.0 then rl:=32000; if rl<0.0 then rl:=0;
  1157.   inte:=trunc(rl);
  1158.   i:=cstr(inte div 3600)+':'; ii:=cstr((inte mod 3600) div 60);
  1159.   if length(ii)=1 then ii:='0'+ii; i:=i+ii+':';
  1160.   ii:=cstr(inte mod 60); if length(ii)=1 then ii:='0'+ii;
  1161.   tlef:=i+ii;
  1162. end;
  1163.  
  1164. procedure phelp;
  1165. var i,lli:str; c:integer; abort,next:boolean;
  1166. begin
  1167.   ihelp:=true;
  1168.   lli:=thisline;
  1169.   if helpl in ['0'..'^'] then
  1170.     if helpi[helpl]>0 then begin
  1171.       cls;
  1172.       c:=helpi[helpl];
  1173.       i:=''; abort:=false;
  1174.       while (help[c]<>'|') and (not abort) do begin
  1175.         if help[c]=#10 then begin
  1176.           printacr(i,abort,next);
  1177.           i:='';
  1178.         end else
  1179.           if help[c]<>#13 then
  1180.             i:=i+help[c];
  1181.         c:=c+1;
  1182.       end;
  1183.       nl; nl; nl;
  1184.       prompt(lli);
  1185.     end;
  1186.   ihelp:=false;
  1187. end;
  1188.  
  1189. procedure ptime;
  1190. var i:str;
  1191. begin
  1192.   if useron then begin
  1193.     i:=thisline;
  1194.     nl; nl; print(dat);
  1195.     print('Time left: '+tlef);
  1196.     nl; prompt(i);
  1197.   end;
  1198. end;